/****************************************************************************
*                                                                           *
* Copyright (c) Ionescu M. Marius. All rights reserved(2010).               *
*                                                                           *
****************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Data;
using System.Web.Security;
using System.Web.UI.HtmlControls;
using System.Configuration;
using System.Collections;
using System.Web.UI.WebControls.WebParts;
using System.Web.Script;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Data.SqlClient;
using System.IO;
using System.Web.UI.WebControls;
using System.Web.UI;

public partial class Communicator : SessionPageBase, ICallbackEventHandler
{
    static string machineIp;
    static int machinePort;

    //Setari pentru baza de date
    static string dbServerName;
    static string dbDataBaseName;
    static string dbUserName;
    static string dbPassword;
    static string machineName;
    static int machineID = 0;

    static SqlConnection sqlConn = null;

    //static TcpClient client = null;
    //static NetworkStream stream = null;

    // Special caracters
    const byte SYN = 0x02;      // SYN = Synchronize
    const byte ACK = 0x06;      // ACK = Acknowledge

    const byte MS = 0x05;       // MS = Message Start
    const byte ME = 0x0A;       // ME = Message End
    const byte SE = 0x04;       // SE = Segment End
    const byte FE = 0x08;       // FE = Field End

    const byte sepMDSD = 0x03;  // MD SD separator
    const byte sepSDFD = 0x0C;  // SD FD separator
    const byte sepFDV = 0x16;   // FD V  fields separator

    // Config file
    static string dbConfigFile = "DbSettings.conf";
    static string comConfigFile = "ComSettings.conf";

    // Log file
    static string logFilename = "APARAT.log";

    static Socket client;
    static Socket newsock;
    static IPEndPoint iep;
    static byte[] data = new byte[1024];
    static int size = 1024;
    static string strMessage;
    Timer tm = new Timer();
    //private NetworkStream ns = null;
    //private byte[] dataBuffer;

    public bool InitPage
    {
        get { return (bool)(this.ViewState["InitPage"] ?? false); }
        set { this.ViewState["InitPage"] = value; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            tm.Tick += new EventHandler<EventArgs>(tm_Tick);
        }

        catch (Exception ex)
        {
            this.SetMessage(ex.Message, true);
        }

    }

    public void tm_Tick(object sender, EventArgs e)
    {
        if(client.Connected)
            client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
    }

    #region ICallbackEventHandler Members

    public string GetCallbackResult()
    {
        return strMessage;
    }

    public void RaiseCallbackEvent(String eventArgument)
    {
        strMessage = eventArgument;
    }

    #endregion

    [WebMethod, ScriptMethod]
    public static string[] getData(bool Init)
    {
        try
        {
            if (Init == true)
            {
            //    Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //    IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5050);
            //    newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
            }

            //else
            //{
            //    client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
            //}
        }
        catch (Exception ex)
        {
            //SessionPageBase.SetMessageStatic(ex.Message, true);
            //throw; // should determine a call to "onGetdataFail"...
            return new string[] { ex.Message };
        }
        return new string[] { strMessage };
    }

    public void ButtonConnectOnClick(object obj, EventArgs ea)
    {
        try
        {
            newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
			iep = new IPEndPoint(IPAddress.Parse("192.168.1.85"), 5050);
            newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
            Session["mySocket"] = newsock;
            InitPage = false;
            tm.Interval = 100;
            tm.Enabled = true;

            lblStatus.Text = "Connecting...";
            lblStatus.BackColor = System.Drawing.Color.Green;
            lblStatus.ForeColor = System.Drawing.Color.White;

            //IAsyncResult ar = newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
            //bool success = ar.AsyncWaitHandle.WaitOne(5000, true);

            //dataBuffer = new byte[client.ReceiveBufferSize];
            client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
            
        }

        catch (Exception ex)
        {
            SessionPageBase.SetMessageStatic(ex.Message, true);
        }
    }

    public void ButtonSendOnClick(object obj, EventArgs ea)
    {
        try
        {
            byte[] message = Encoding.ASCII.GetBytes(txtData.Text);
            txtData.Text = "";
            client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendData), client);
        }
        catch (Exception ex)
        {
            SessionPageBase.SetMessageStatic(ex.Message, true);
        }
    }

    private void ButtonDisconOnClick(object obj, EventArgs ea)
    {
        try
        {
            client.Close();
            lblStatus.Text = "Disconnected";
        }
        catch (Exception ex)
        {
            SessionPageBase.SetMessageStatic(ex.Message, true);
        }
    }

    public void Connected(IAsyncResult iar)
    {
        client = (Socket)iar.AsyncState;
        try
        {
            client.EndConnect(iar);
            //lblStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
            client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
        }
        catch (SocketException)
        {
            //lblStatus.Text = "Error connecting";
        }
    }

    public void ReceiveData(IAsyncResult iar)
    {
        Socket remote = (Socket)iar.AsyncState;
        int recv = remote.EndReceive(iar);
        string stringData = Encoding.ASCII.GetString(data, 0, recv);

        //txtData.Text = "\n" + stringData;
        //strData = stringData;

        string js = "onGetdataSuccess('" + stringData + "')";
        ScriptManager.RegisterStartupScript(this, typeof(Communicator), "receive", js, true);

    }

    private void SendData(IAsyncResult iar)
    {
        Socket remote = (Socket)iar.AsyncState;
        int sent = remote.EndSend(iar);
        remote.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), remote);
    }


    public void InsertAndLogReceivedData(object machineID, object sampleID, object anCode, object refCode, object stringValue)
    {
        SqlCommand cmdInsert = new SqlCommand();
        cmdInsert.Connection = sqlConn;
        cmdInsert.CommandType = CommandType.Text;
        cmdInsert.CommandText = " INSERT INTO RESULTS_BUFFER (MachineID, SampleID, AnCode, RefCode, StringValue, ProcDate, TransDate) " +
                                " VALUES (" + System.Convert.ToInt32(machineID) + ", " + System.Convert.ToInt32(sampleID) + ", '" + anCode + "', '" + refCode + "', '" + stringValue + "', '" + DateTime.Now + "', '" + DateTime.Now + "')";
        cmdInsert.ExecuteNonQuery();

        StreamWriter sw = new StreamWriter(machineName + ".activity.log", true);
        sw.WriteLine(cmdInsert.CommandText);
        sw.Close();
    }

    private void ParseReceivedData()
    {
        try
        {
            StreamReader sr = new StreamReader(logFilename);
            string fileContent = sr.ReadToEnd();
            string[] analyses = fileContent.Split(new string[] { "CTR" }, StringSplitOptions.None);
            string partialAnalyse = "";
            foreach (string analyse in analyses)
            {
                string anCode, refCode, stringValue, sampleID = "";

                if (analyse.Length > 1)
                {
                    partialAnalyse = analyse.Substring(0, analyse.IndexOf("TestTime"));

                    // Afla SampleID
                    //string sampleSegments = partialAnalyse.Substring(analyse.IndexOf("SampleID"));
                    //string[] nameAndValueSample = sampleSegments.Split(new char[] { Convert.ToChar(FE) });
                    //string[] valueSample = nameAndValueSample[0].Split(new char[] { Convert.ToChar(sepFDV) });
                    //sampleID = valueSample[1];

                    if (analyse.IndexOf("Name") != -1)
                    {

                        string sampleSegments = partialAnalyse.Substring(analyse.IndexOf("Name"));
                        string[] nameAndValueSample = sampleSegments.Split(new char[] { Convert.ToChar(FE) });
                        string[] valueSample = nameAndValueSample[0].Split(new char[] { Convert.ToChar(sepFDV) });
                        sampleID = valueSample[1];

                        string secondPartialAnalyse = partialAnalyse.Substring(0, analyse.IndexOf("ALY#") - 1);

                        Console.WriteLine("Am primit HEMOGRAMA pentru cererea:" + sampleID.ToString());
                        // Afla datele despre analiza
                        secondPartialAnalyse = secondPartialAnalyse.Replace(Convert.ToChar(sepMDSD), ' ');
                        string[] segments = secondPartialAnalyse.Split(new char[] { Convert.ToChar(SE) });
                        foreach (string segment in segments)
                        {
                            string[] fields = segment.Split(new char[] { Convert.ToChar(sepSDFD) });
                            anCode = "MINDRAYBC5500";
                            refCode = fields[0].Trim();
                            string[] nameAndValue = fields[1].Split(new char[] { Convert.ToChar(FE) });
                            string[] value = nameAndValue[0].Split(new char[] { Convert.ToChar(sepFDV) });
                            stringValue = value[1];

                            // Insert analiza in baza de date (si log-are in fisier) 
                            InsertAndLogReceivedData(machineID, sampleID, anCode, refCode, stringValue);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Am primit anlize fara numar de identificare, O IGNOR!!!");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            this.SetMessage(ex.Message, true);
        }
    }

    private void InitializeConnections()
    {

        #region Initializare COM

        try
        {
            if (File.Exists(comConfigFile))
            {
                using (StreamReader sr = File.OpenText(comConfigFile))
                {
                    string commentLine = sr.ReadLine();		// [Machine IP]
                    machineIp = sr.ReadLine();	        // 

                    commentLine = sr.ReadLine();			// [Machine PORT]
                    machinePort = Convert.ToInt32(sr.ReadLine());
                }
            }
            else
            {
                Console.WriteLine("ERROR: Nu exista fisierul de configurare ComSettings.conf.");
                return;
            }
        }
        catch (Exception ex)
        {
            this.SetMessage(ex.Message, true);
            return;
        }

        Console.WriteLine("Citire fisier de configurare ComSettings.conf...\tOK");

        #endregion

        #region Initializare DB
        try
        {
            if (File.Exists(dbConfigFile))
            {
                using (StreamReader sr = File.OpenText(dbConfigFile))
                {
                    string commentLine = sr.ReadLine();		// [Database server]
                    dbServerName = sr.ReadLine();	        // 

                    commentLine = sr.ReadLine();			// [Database name]
                    dbDataBaseName = sr.ReadLine();

                    commentLine = sr.ReadLine();			// [Username]
                    dbUserName = sr.ReadLine();

                    commentLine = sr.ReadLine();			// [Password]
                    dbPassword = sr.ReadLine();

                    commentLine = sr.ReadLine();			// [Machine name]
                    machineName = sr.ReadLine();
                }
            }
            else
            {
                this.SetMessage("ERROR: Nu exista fisierul de configurare DbSettings.conf.", true);
                return;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("\nEROARE: {0}\n", e);
            return;
        }

        Console.WriteLine("Citire fisier de configurare DbSettings.conf...\t\tOK");

        #endregion

        #region Conexiunea la baza de date

        string sqlConnString = "Server=" + dbServerName + ";Database=" + dbDataBaseName + ";User ID=" + dbUserName + ";Password=" + dbPassword;

        try
        {
            sqlConn = new SqlConnection(sqlConnString);
            sqlConn.Open();
        }
        catch (Exception e)
        {
            Console.WriteLine("\nEROARE: {0}\n", e);
            return;
        }

        Console.WriteLine("Conexiunea la baza de date...\t\t\t\tOK");

        #endregion

        #region Verifica daca exista aparatul in baza de date

        try
        {
            SqlCommand cmdMachineID = new SqlCommand();
            cmdMachineID.Connection = sqlConn;
            cmdMachineID.CommandType = CommandType.Text;
            cmdMachineID.CommandText = " SELECT ID FROM MACHINES " +
                                        " WHERE Name LIKE '%" + machineName.ToUpper() + "%'";

            machineID = Convert.ToInt32(cmdMachineID.ExecuteScalar());
        }
        catch (Exception e)
        {
            Console.WriteLine("\nEROARE: {0}\n", e);
            return;
        }

        if (machineID == 0)
        {
            this.SetMessage("ERROR: The lab equipment was not found in the database.", true);
            return;
        }

        Console.WriteLine("Aparatul a fost gasit in baza de date...\t\tOK");
        #endregion

        #region Sterge vechile fisiere .log si .activity.log
        File.Delete(machineName + ".log");
        File.Delete(machineName + ".activity.log");
        #endregion

    }
}
